/* Copyright 2008 Shawn C. Dodd

This file is part of TagFC.  TagFC is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

TagFC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with TagFC.  If not, see <http://www.gnu.org/licenses/>. */

class DashboardController {

    def index = { 
	// read sample data 
//	def testFileName = "timesheet-test-data.html"
//	def testFileFile = new File(testFileName)
//	def tsheetTbl = new XmlSlurper().parse(testFileFile)

	// collect data for charts
	def pieTally = [:]
	def effTodayTally = [:]
	long pieRange = 0
	long[] hourlyTallyTags = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
	long[] hourlyTallySeen = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
	long[] weekTallyRate = [0,0,0,0,0,0,0]
	long[] weekTallyTags = [0,0,0,0,0,0,0]
	long[] weekTallySeen = [0,0,0,0,0,0,0]
	def lastMod = new Date()		// new Date(testFileFile.lastModified())
	def today = new Date()
//	tsheetTbl.body.div.div.table.tbody.tr.each { tr ->
	def sheets = Timesheet.list()			// note: won't scale; need running averages
	sheets.each { sheet ->
		// for pie
		def n = sheet.nickname.displayName		// assume displayName is unique
		long t = sheet.totalCompleted
		pieRange += t
		if( !pieTally[n] ) pieTally[n] = 0
		pieTally[n] += t

		// for rate
		long s = sheet.totalSeen

		// for hourly
		def p = sheet.period
		int h = p[-2..-1].toLong()
		hourlyTallyTags[h] += t
		hourlyTallySeen[h] += s

		// for week rate
		// TODO  use .dateCreated instead of .period
		Date d = sheet.dateCreated
		if( minusDaywise( d, today ) > -7 ) {
			int offset = minusDaywise( d, today ) - 1
			weekTallySeen[offset] += s
			weekTallyTags[offset] += t
		}
		
		// for today's efficiency
		if( sameDay(d, today) ) {
			if( !effTodayTally[n] ) effTodayTally[n] = [tags:0L,seen:0L,rate:0L]
			effTodayTally[n].tags += t
			effTodayTally[n].seen += s
		}
	}
	pieTally = pieTally.entrySet().sort{ it.value }.reverse()
	def pieList = pieTally.subList(0,5)
	pieList << ["Other":pieTally.subList(5,pieTally.size()).inject(0){c,i -> c+i.value}].entrySet().toList()[0]
	for( idx in 0..weekTallyRate.length-1 ) weekTallyRate[idx] = makeRateFromLongs( weekTallyTags[idx], weekTallySeen[idx], 1 )
	effTodayTally.each { it.value.rate = makeRateFromLongs( it.value.tags, it.value.seen, 1 ) }
	log.error "pieList: $pieList"
	log.error "hourlyTallyTags: $hourlyTallyTags"
//	log.error "weekTallySeen: $weekTallySeen"
//	log.error "weekTallyTags: $weekTallyTags"
	log.error "weekTallyRate: $weekTallyRate"
	log.error "effTodayTally: $effTodayTally"

	// and view
	[ asOfDate:lastMod,
	  tbfNicknames:pieList.collect{it.key}, 
	  tbfSlices:pieList.collect{it.value},
	  tddData:hourlyTallyTags.toList(),
	  sddData:hourlyTallySeen.toList(),
	  trlwData:weekTallyRate.toList(),
	  etNicknames:effTodayTally.collect{it.key},
	  etData:effTodayTally.collect{it.value.rate} ]
    }

    /* Returns percentage with given precision (useful for charts where approximation is acceptable).
    * NUMERATOR  DENOMINATOR  DECIMALS  OUTPUT  COMMENT
    * 2          100          0         2       2%
    * 2          100          1         20      2.0%
    * 21         1000         0         2       2%
    * 21         1000         1         21      2.1%
    */
    long makeRateFromLongs( long numerator, long denominator, int decimals ) {
	long multiplier = 100*10**decimals		// recall that operator ** is exponentiation
	return numerator * multiplier / denominator
    }

    boolean sameDay( Date a, Date b) {
	Calendar aye = Calendar.getInstance(), bee = Calendar.getInstance()
	aye.setTime(a)
	bee.setTime(b)
	return aye.get(Calendar.YEAR) == bee.get(Calendar.YEAR) && aye.get(Calendar.DAY_OF_YEAR) == bee.get(Calendar.DAY_OF_YEAR)
    }

    long minusDaywise( Date a, Date b ) {
    	long diff = a.getTime() - b.getTime()
	return diff/24/60/60/1000		// close enough
    }

}
